package com.gmrz.webauthn.handler;

import com.gmrz.uaf.common.Constants;
import com.gmrz.uaf.db.UAFDAOFactory;
import com.gmrz.uaf.db.UAFDBConnectionMgr;
import com.gmrz.uaf.protocol.v1.json.UAFSchemaBuilder;
import com.gmrz.uaf.server.ServerContext;
import com.gmrz.uaf.servlet.v1.handler.UAFBaseHandler;
import com.gmrz.uaf.servlet.v1.request.ReceiveReqPayload;
import com.gmrz.uaf.servlet.v1.validation.PayloadValidationException;
import com.gmrz.uaf.servlet.v1.validation.RestValidator;
import com.gmrz.util.db.DBUtil;
import com.gmrz.webauthn.db.dao.WebAuthnAuthenticatorsDAO;
import com.gmrz.webauthn.protocol.v1.schema.WebAuthenticator;
import com.gmrz.webauthn.request.WebAuthnRespPayload;
import com.gmrz.webauthn.request.WebRegListContext;
import com.gmrz.webauthn.response.WebAuthnAuthenticator;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Type;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

public class WebRegListHandler extends UAFBaseHandler {
    private static final Logger LOG = LogManager.getLogger(WebRegListHandler.class);

    public String list(String request) {
        LOG.info("[/reg/list][begin]");
        ServerContext.getServerContext().getFidoLog().setRequest(request);
        Gson gson = UAFSchemaBuilder.getGson();
        Type reqType = new TypeToken<ReceiveReqPayload<WebRegListContext>>() {
        }.getType();
        WebAuthnRespPayload<WebAuthnAuthenticator> respPayload = new WebAuthnRespPayload<WebAuthnAuthenticator>();

        String response = null;
        ReceiveReqPayload<WebRegListContext> reqPayload = null;

        Connection conn = null;

        try {
            reqPayload = gson.fromJson(request, reqType);
            logRequest(request, reqPayload.getContext().getTransNo(), reqPayload.getContext().getUserName(),
                    reqPayload.getContext().getAppID(), reqPayload.getContext().getAuthType(), reqPayload.getContext().getTransType(), Constants.Method.DEREG_ONE);
            validate(reqPayload);


            WebRegListContext context = reqPayload.getContext();
            String hashedUserName = generateHashedUserName(context.getUserName(), context.getRf1(), context.getRf2());
            String deviceID = reqPayload.getContext().getDeviceID();
            conn = UAFDBConnectionMgr.getConnection();
            WebAuthnAuthenticatorsDAO webauthnAuthenticatorsDAO = UAFDAOFactory.createWebAuthnAuthenticatorsDAO(conn);
            List<WebAuthenticator> authenticators = webauthnAuthenticatorsDAO.find(reqPayload.getContext().getAppID(), hashedUserName,reqPayload.getContext().getAuthType(),reqPayload.getContext().getTransType(),deviceID);
            List<WebAuthnAuthenticator> authnAuthenticators = new ArrayList<WebAuthnAuthenticator>();
            if(null != authenticators && !authenticators.isEmpty()){
                for(WebAuthenticator authenticator : authenticators){
                    WebAuthnAuthenticator authnAuthenticator = new WebAuthnAuthenticator();
                    authnAuthenticator.setAaguid(authenticator.getAaguid().toString());
                    authnAuthenticator.setAuthType(authenticator.getAuthType());
                    authnAuthenticator.setTransType(authenticator.getTransType());
                    authnAuthenticator.setDeviceID(authenticator.getDeviceId());
                    authnAuthenticator.setKeyID(authenticator.getCredentialId());
                    authnAuthenticator.setCreatets(authenticator.getCreateTimeStamp().getTime());
                    authnAuthenticators.add(authnAuthenticator);
                }
            }
            respPayload.setAuthenticators(authnAuthenticators);
            respPayload.setStatusCode(Constants.StatusCode.OK.getCode());
            respPayload.setDescription("OK");
            response = gson.toJson(respPayload);
        } catch (Exception ex) {
            LOG.info("reg list error");
            LOG.error(ex);
            response = buildWebAuthnRespFromException(respPayload, ex);
        }finally {
            DBUtil.close(conn);
        }
        LOG.info("[/reg/list][end]");
        return response;
    }

    private void validate(ReceiveReqPayload<WebRegListContext> reqPayload) throws PayloadValidationException {
        if ((reqPayload == null) || (reqPayload.getContext() == null)) {
            throw new PayloadValidationException("context", RestValidator.VALIDATION_ERROR.EMPTY);
        }
        WebRegListContext context = reqPayload.getContext();
        RestValidator.validate("userName", context.getUserName());
        RestValidator.validate("appID", context.getAppID());
        RestValidator.validate("authType", context.getAuthType());
        RestValidator.validate("transType", context.getTransType());
        RestValidator.validate("transNo", context.getTransNo());
        RestValidator.validate("rf1", context.getRf1());
        RestValidator.validate("rf2", context.getRf2());
    }

}
